package utils {
	
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author Vjekoslav Ratkajec
	 */
	public class Navigation extends MovieClip {
		
		//contains all MovieClips which acts like buttons
		private var subscribedMovieClips:Array = new Array();
		//list of callback functions registered for buttons
		private var clickFunctions:Array = new Array();
		//list of permissions if button will be reseted when other button is clicked
		private var subscribedMovieClipsResetPermission:Array = new Array();
		//currently active (clicked) button
		private var activeButton:MovieClip;
		
		public function Navigation() {
			
		}
		
		/**Adds subscriber to subscribedMovieClips array.
		 * 
		 * @param	button	desired MovieClip to add
		 */
		public function addSubscriber(button:MovieClip, resetOtherButtonsOnClick:Boolean = true, mouseClickFunction:Function = null):void {
			//find next free position in array
			var nextSubscriberNumber:uint = subscribedMovieClips.length;
			//add button in subscriber array
			subscribedMovieClips[nextSubscriberNumber] = button;
			subscribedMovieClipsResetPermission[nextSubscriberNumber] = resetOtherButtonsOnClick;
			//set properties
			subscribedMovieClips[nextSubscriberNumber].buttonMode = true;
			subscribedMovieClips[nextSubscriberNumber].addEventListener(MouseEvent.CLICK, mouseClickHandler);
			subscribedMovieClips[nextSubscriberNumber].addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
			subscribedMovieClips[nextSubscriberNumber].addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
			//set null or callback function in functions array
			clickFunctions[nextSubscriberNumber] = mouseClickFunction;
		}
		
		/**Removes subscriber form subscribedMovieClips array.
		 * 
		 * @param	button	desired MovieClip to remove
		 */
		public function removeSubscriber(button:MovieClip):void {
			//find position in array
			var subscriberIndex:uint = searchSubscriberIndex(button);
			//remove properties
			subscribedMovieClips[subscriberIndex].buttonMode = false;
			subscribedMovieClips[subscriberIndex].removeEventListener(MouseEvent.CLICK, mouseClickHandler);
			subscribedMovieClips[subscriberIndex].removeEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
			subscribedMovieClips[subscriberIndex].removeEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
			
			//remove button from subscriber and function array
			subscribedMovieClips.splice(subscriberIndex, 1);
			clickFunctions.splice(subscriberIndex, 1);
		}
		
		/**Method which finds desired MovieClip in subscribedMovieClips array and returns it position in that array.
		 * 
		 * @param	button		MovieClip which we want to find
		 * @return	number of MovieClip in subscribedMovieClips array
		 */
		private function searchSubscriberIndex(button:MovieClip):int {
			//later implemet check for unknown MovieClips
			var subscriberIndex:int = -1;
			for (var i:uint = 0; i < subscribedMovieClips.length; i++) {
				if (subscribedMovieClips[i] == button) {
					subscriberIndex = i;
					break;
				}
			}
			return subscriberIndex;
		}
		
		/**Method which resets all MovieClips besides new active MovieClip
		 * 
		 * @param	button	MovieClip which is clicked and all else subscribed must be deactivated
		 */
		private function resetAllSubscribersBesidesActive(button:Object):void {
			for (var i:uint = 0; i < subscribedMovieClips.length; i++) {
				if (subscribedMovieClips[i] != button) {
					subscribedMovieClips[i].gotoAndStop("normalUp");
				}
			}
		}
		
		/**Method to set MovieClip in Over state.
		 * 
		 * @param	event	MOUSE_OVER on MovieClip
		 */
		private function mouseOverHandler(event:MouseEvent):void {
			if (event.currentTarget.currentLabel == "normalUp") {
				event.currentTarget.gotoAndStop("normalOver");
			} else if (event.currentTarget.currentLabel == "clickedUp") {
				event.currentTarget.gotoAndStop("clickedOver");
			}
		}
		
		/**Method to set MovieClip in Up state when mouse leaves.
		 * 
		 * @param	event	MOUSE_OUT on MovieClip
		 */
		private function mouseOutHandler(event:MouseEvent):void {
			if (event.currentTarget.currentLabel == "normalOver") {
				event.currentTarget.gotoAndStop("normalUp");
			} else if (event.currentTarget.currentLabel == "clickedOver") {
				event.currentTarget.gotoAndStop("clickedUp");
			}
		}
		
		/**Method to set MovieClip in clicked (or normal) state when button is clicked, and optionally call callback function.
		 * 
		 * @param	event	CLICK on MovieClip
		 */
		private function mouseClickHandler(event:MouseEvent):void {
			//find position in array
			var subscriberIndex:uint = searchSubscriberIndex(MovieClip(event.currentTarget));
			//set callback function
			var callbackFunction:Function = clickFunctions[subscriberIndex];
			//reset all buttons besides active
			if(subscribedMovieClipsResetPermission[subscriberIndex]) {
				resetAllSubscribersBesidesActive(event.currentTarget);
				activeButton = MovieClip(event.currentTarget);
			}
			
			if (event.currentTarget.currentLabel == "normalOver") {
				event.currentTarget.gotoAndStop("clickedOver");
				//if callbackfunction is defined, call it
				if(callbackFunction != null) {
					callbackFunction(MovieClip(event.currentTarget));
				}
			} else if (event.currentTarget.currentLabel == "clickedOver") {
				event.currentTarget.gotoAndStop("normalOver");
				//if callbackfunction is defined, call it
				if(callbackFunction != null) {
					callbackFunction(MovieClip(event.currentTarget));
				}
			} else {
				trace("Incorrect label in: " + event.currentTarget.name);
			}
		}
		
		//Method which retrieves active button instance
		public function get getActiveButton():MovieClip {
			return this.activeButton;
		}
	}

}